/**
 * @module NGS
 * @description NGS框架类模块
 */
(function($) {
	/**
	 * 初始时候就重定义window.Nodification，避免ckeditor造成的冲突
	 */
	var Notification = window.Notification;

	var NGSWebsocket = function(type) {
		this.address = '';
		this.type = type;
		this.listeners = [];
	};
	NGSWebsocket.prototype = {
		eventHandle: function(e) {
			var a = this;
			$.each(a.listeners, function(i, listener) {
				if (listener) {
					if (!listener.token|| listener.token === e.refid) {
						if (a === $E.ws.framework)
							listener.callback(e, listener.ev);
						else
							listener.callback(e.data, listener.ev);

						if (! listener.persistence)
							a.listeners.remove(listener); //a.listeners.splice(i, 1);
						// return false;
					}
				}
			})
		},

		hook : function(token, callback, ev, persistence) {
			var a = this;
			a.listeners.push({
				token : token,
				callback : callback,
				ev : ev,
				persistence : persistence
			})
		},

		/**
		 * 通过WebSocket发送消息
		 * @method send
		 * @param module {string} 服务名称
		 * @param data {any} 发送的消息对象
		 * @param [callback] {callback} 需要请求回调的方法
		 * @param [ev] {any} 回调的环境参数
		 */
		send : function(module, data, callback, ev) {
			var a = this, options = module;
			if ($.type(module) !== 'object') {
				options = {
					module: module,
					data: data,
					callback: callback,
					ev: ev
				}
			}
			options.data = options.data || {};
			if ($.type(options.data) == 'string') {
				options.data = {
					data: options.data
				}
			}
			var token = options.data.refid || Guid.raw();
			options.data['refid'] = token;
			options.data['module'] = options.module;
			if ($.isFunction(options.callback)) {
				a.hook(token, options.callback, options.ev);
			}
			try {
				if (! a.proxy) {
					if ($.isFunction(options.callback)) {
						a.eventHandle({
							refid : token,
							data : {
								code : -1,
								message : 'WebSocket未准备就绪'
							}
						})
					}
				} else {
					//$F.log('WebSocket - Send', JSON.stringify(data));
					a.proxy.send(JSON.stringify(options.data));
				}
			} catch (e) {
				$F.err('WebSocket - Send', e);
				if ($.isFunction(options.callback)) {
					a.eventHandle({
						refid : token,
						data : {
							code : -1,
							message : e
						}
					})
				}
			}
		}
	}

	/**
	 * __系统顶级类：$E__，用于管理系统框架
	 *
	 * @class $E
	 * @author Kevin.MOU
	 */
	var $E = {
		/**
		 * 框架版本号
		 *
		 * @property version
		 * @type {string}
		 * @static
		 */
		version : 'NGS-1.5-20190403',
		debug: true,

		/**
		 * 服务所在的 Web application context
		 *
		 * @property url
		 * @type {string}
		 */
		url : '',

		/**
		 * 当前框架的数据服务连接
		 *
		 * @property dataService
		 * @type {object}
		 */
		dataService : {},

		/**
		 * 当前框架定义的所有插件服务地址
		 * @property pluginServices
		 * @type {object}
		 */
		pluginServices : {},

		/**
		 * 当前服务的HTTP地址
		 * @property host
		 * @type {string}
		 */
		host : '',

		/**
		 * 当前登录员工账号对象
		 *
		 * 	staff : {
		 * 		id: {string} staffId,
		 * 		name: {string} staffName,
		 * 		agentId: {string},
		 * 		loginName: {string},
		 * 		epid: {string},
		 * 		groupId: {string},
		 * 		groupName: {string},
		 * 		remoteKey: {string} 账户登录系统携带的识别码（有客户端框架生成的GUID，保存于cookie中）
		 * 		roles: {array}
		 * 		loginTime: {long}
		 * 		epidSql: {string}
		 * 	}
		 *
		 * @property staff
		 * @type {object}
		 */
		staff : {},

		/**
		 * 多项目库
		 * @property projects
		 * @type {object}
		 * @private
		 */
		projects : {},

		/**
		 * 软电话对象
		 */
		softphone : undefined,

		/**
		 * 异步执行基类
		 *
		 * @property async
		 * @type {object}
		 * @private
		 */
		async : undefined,

		/**
		 * 框架插件
		 * @property plugins
		 * @type {object}
		 */
		plugins : {},

		/**
		 * 系统级别静态数据缓存
		 * @property caches
		 * @type {object}
		 */
		caches : {},

		jsv : '',
		jcropApi : false,
		WebNotification : Notification,
		windowOnFocus : true,
		lang : 'zh_CN',
		live : new Date().getTime(),

		/**
		 * 全局类：$E.events, 提供消息事务管理
		 * @class $E.events
		 */
		events : undefined,

		/**
		 * 全局类：$E.ws, 管理ngs框架的websocket服务
		 */
		ws: {
			local: new NGSWebsocket(),
			workload: new NGSWebsocket(),
			framework: new NGSWebsocket()
		},

		grpChange: function() {
			const me = this,
				proj = me.getActiveProject(),
				dom = $('<div style="width:100%;height:100%"></div>');

			let selected;
			$F.createDialog(dom, {
				title: '切换用户组',
				icon: '[l]repeat-alt',
				removable: true,
				resizable: {
					cookie: 'group.change.dialog',
					minWidth: '200px',
					minHeight: '100px'
				},
				contentCSS: {
					padding: 0
				},
				width: '400px',
				height: '200px',
				onOpen: function() {
					let dialog = this,
						list = dom.wisList({
							border: false,
							onChange: function(data) {
								selected = data[0];
								$('.js_submit', dialog).prop('disabled', selected.value == proj.groupId);
							},
							onDblClick: function(data) {
								selected = data[0];
								if (selected.value !== proj.groupId)
									$('.js_submit', dialog).prop('disabled', false).trigger('click')
							}
						});
					$('.js_submit', dialog).prop('disabled', true);
					$F.dataService('SystemDo2', {
						data: $F.sqlbean('System.Staff.getGroups', proj.token),
						digest: proj.digest,
						successResult: function(data) {
							let cs = [];
							data[0].fields.forEach(item=> {
								if (item[0] == proj.groupId) {
									cs.push({
										label: item[1] + " (当前组)",
										value: item[0]
									})
								} else {
									cs.push({
										label: item[1],
										value: item[0]
									})
								}
							})
							list.setData(cs)
						}
					})
				},
				onSubmit: function(close) {
					close();

					$F.dataService('JSGenerateServlet', {
						data: {
							token : proj.token,
							clsName: 'elite.sysfun.root.ChangeCurrentGroup',
							rolegroupId: selected.value
						},
						digest: proj.digest,
						successResult: function() {
							$E.staff.current.groupId = proj.groupId = selected.value;
							$E.staff.current.groupName = proj.groupName = selected.label;
							$('#c_user .js_group').text(proj.groupName);
							proj.tabCloseAll(true);
							proj.initParameters(() => {
								proj.initMenus();
								proj.start();
							});
						}
					})
				},
				onCancel :function(close) {
					close();
				}
			})
		},

		pwdChange : function(force) {
			var a = this,
				proj = a.getActiveProject();
			if (!proj)
				return $F.alert('当前无项目');

			var token = proj.token,
				dialog = $('#staffPasswordChange');
			$('.js_close', dialog).prop('disabled', force);
			$('.close_tip_icon', dialog).toggle(!force);

			$('input[name=oldpwd]', dialog).val('');
			$('input[name=newpwd]', dialog).val('');
			$('input[name=newpwd2]', dialog).val('');
			$F.dialogOpen(dialog, {
				onOpen : function() {
					$('input[name=oldpwd]', dialog).focus();
				},
				onSubmit : function() {
					var oldpwd = $('input[name=oldpwd]', dialog).val(),
						newpwd = $('input[name=newpwd]', dialog).val(),
						newpwd2 = $('input[name=newpwd2]', dialog).val();
					if (newpwd !== newpwd2)
						return $F.alert($F.lang('sys.pwdRepeatInvalid'), function() {
							$('input[name=newpwd2]', dialog).select().focus();
						});

					$F.dataService('JSGenerateServlet2', {
						data : {
							token : token,
							dbPool : '',
							name : "System.StaffInfo.ChangeP",
							o : $F.encPwd(oldpwd, a),
							n : $F.encPwd(newpwd, a, true),
							uid: a.uid
						},
						digest: proj.digest,
						success : function(data) {
							if (data.code > 0) {
								$F.dialogClose(dialog);
								$F.info($F.lang('sys.pwdChanged'), ()=>{
									$E.logout()
								});
							} else {
								if (data.code === -55 || data.code === -56) {
									$F.alert('原密码错误超过最大次数，账号已锁定', ()=>{
										$E.logout()
									});
								} else {
									$F.alert(data.code === -7 ? '原密码错误':data.message, function() {
										$('input[name=oldpwd]', dialog).select().focus()
									});
								}
							}
						}
					})
				}
			});
			$('input[name=oldpwd]', dialog).focus();
		},

		/**
		 * 获取当前激活的项目对象
		 * @method getActiveProject
		 * @return {project} 项目对象
		 */
		getActiveProject : function() {
			const a = this;
			for (let id in a.projects) {
				if (a.projects[id].state)
					return a.projects[id];
			}
			$F.err('Elite - getActiveProject', '系统错误，没有发现当前项目');
			return undefined;
		},

		getCurrentToken : function() {
			return this.getActiveProject().token;
		},

		isAdminRole : function() {
			var roles = this.getActiveProject().roles;
			for (var i = 0; i < roles.length; i++) {
				if (roles[i].id == 'G00001')
					return true;
			}
			return false;
		},

		/** 获取theme配置 **/
		getSysTheme : function() {
			const a = this;
			const proj = a.getActiveProject()
			$F.dataService('SystemDo2', {
				data: $F.sqlbean('System.theme', proj.token, []),
				digest: proj.digest,
				success: function(data) {
					if (data.code > 0) {
						const themeArray = data.value[0].fields;
						if(themeArray.length && themeArray.length > 0) {
							$('#uicfgDialog #themeChange').css('display','block')
							for (let i = 0; i < themeArray.length; i++) {
								$('#uicfgDialog option[value='+ themeArray[i][0] +']').css('display','block')
							}
						}
					} else
						$F.err(data.message);
				}
			})
		},

		/**
		 * 打开一个插件
		 * @method openPlugin
		 * @param tabName {string} TAB标签
		 * @param project {project} 项目对象
		 * @param addin {string | object} 组件对象
		 * @param addinParam {any} 组件参数
		 * @param [parameter] {any} 插件入参
		 * @param keepOpen {boolean} 是否不允许关闭
		 */
		openPlugin : function(tabName, project, addin, addinParam, parameter, keepOpen) {
			var a = this;
			if ($.type(addin) == 'string') {
				var addinObj = project.getAddin(addin.toUpperCase());
				if (!addinObj) {
					//console.log(project.addins)
					$F.alert('未定义的系统组件：' + addin);
					return;
				}
				addin = addinObj;
			}
			project.openAddinPlugin(tabName, addin, addinParam, parameter, keepOpen);
		},

		/**
		 * 在制定的容器内打开一个插件
		 * @method openPlugin
		 * @param ctl {object} PANEL对象
		 * @param project {project} 项目对象
		 * @param addin {string | object} 组件对象
		 * @param addinParam {any} 组件参数
		 * @param [parameter] {any} 插件入参
		 * @param [callback] {function} 回调
		 * @param [async] {boolean} 是否是异步
		 */
		embPlugin : function(ctl, project, addin, addinParam, parameter, callback, async = false) {
			if ($.type(addin) === 'string') {
				var addinObj = project.getAddin(addin.toUpperCase());
				if (!addinObj) {
					$F.alert('未定义的系统组件：' + addin);
					return;
				}
				addin = addinObj;
			}
			if ($.isFunction(ctl.getContainer)) {
				project.embAddinPlugin(ctl.getContainer(), addin, addinParam, parameter, callback, async);
			} else {
				$F.err('Elite - embPlugin', '不可用的容器对象');
			}
		},

		/**
		 * 把框架菜单部分锁住，disable掉
		 */
		frameLock : function(option) {
			$('<div class="js_frame_masker wrapper" />').appendTo($('#sideBar'));
			$('<div class="js_frame_masker wrapper" />').appendTo($('#mainMarquee'));
			if (option && !option.withoutHeader) {
				$('<div class="js_frame_masker wrapper" />').appendTo($("header"));
			} else {
				$('<div class="js_frame_masker wrapper" />').appendTo($('header .c_me'));
			}
			$('<div class="js_frame_masker wrapper" />').appendTo($('footer'));
			$('#mainContainer').addClass('locked');
			this.getActiveProject().lockTabs(true);
		},

		/**
		 * 把框架菜单部分解锁
		 */
		frameUnLock : function() {
			$('#sideBar>.js_frame_masker').remove();
			$('#mainMarquee>.js_frame_masker').remove();
			$('header>.js_frame_masker').remove();
			$('header .c_me>.js_frame_masker').remove();
			$('footer>.js_frame_masker').remove();
			$('#mainContainer').removeClass('locked');
			this.getActiveProject().lockTabs(false);
		},

		headImg : function() {
			var a = this, proj = a.getActiveProject();
			H5Utils.cutImg({
				oldPhoto : $E.staff.headImg,
				masker : $E.url + '/images/bluemanmxxl.png',
				fsPath : '/headimg',
				aspectRatio : 1
			}, function(result) {
				if (result.code > 0) {
					var headimg = result.value;
					$F.dataService('SystemDo1', {
						data : $F.sqlbean('System.Staff.headimgChange', proj.token, [ $E.staff.epidSql, $E.staff.id, headimg ]),
						digest: proj.digest,
						success : function(data) {
							if (data.code > 0) {
								$F.notify($F.lang('message.updateheadimgsuccess'));
								if ($E.staff.headImg) {
									Ajax.post({
										url : $E.url + "/fs/remove_?file=" + $E.staff.headImg,
										async : false,
										success : function(data) {
											if (data.code < 0)
												$F.err('Elite - headImg', data.message);
										}
									})
								}
								$E.staff.headImg = headimg;
								Ajax.post({
									url : $E.url + '/headImgChange_?file=' + $E.staff.headImg,
									async : false,
									success : function(data) {
										if (data.code < 0)
											$F.err('Elite - headImg', data.message);
									}
								})
								$('header img.c_me_pic').attr('src', $E.url + '/fs/get?file=' + headimg);
							} else {
								$F.err('Elite - headImg', data.message);
							}
						}
					})
				}
				else
					$F.err('H5Utils - cutImgChange', result.message);
			})
		},

		/**
		 * 扩展右侧区域，并进行显影切换
		 * @param force {boolean} 是否强行显示
		 * @param recreate {boolean} 是否重新构建，重新构建的话，会清除原来的splitter，重新创建一个新的splitter
		 */
		openChatPanel : function(force, recreate) {
			var a = this,
				areaContainer = $("#areaContainer"),
				splitter = areaContainer.data('wisSplitter'),
				proj = a.getActiveProject(),
				swapRL = $.cookie("chat.swapRL") || proj.getParam('SWAPRL'),
				switcher = proj.chatSwitch;

			if (proj.getParam('CHALOC') === 'embed') {
				proj.events.notify('__OPEN_CHAT__');// 如果是嵌入动态页面的话，发出事件
				return;
			}

			if (!switcher)
				return;

			if (splitter && recreate) {
				splitter.destroy();
				splitter = undefined;
			}
			if (splitter) {
				if (force && !splitter.dockState)
					return;
				if (swapRL === 'right') {
					splitter.dock('1st');
				} else {
					splitter.dock('2nd');
				}
			} else {
				if (swapRL === 'right') {
					$("#chatPanel").after($('#mainContainer'));
				} else {
					$("#mainContainer").after($('#chatPanel'));
				}
				splitter = areaContainer.wisSplitter({
					direct : 'h',
					cookie : 'splitter.chat',
					fixedSize: swapRL === 'right' ? window.innerWidth / 3 : window.innerWidth * 2 / 3,
					minSize : 300,
					startMove : function() {
						$('<div class="bodyMasker" style="position: absolute;top: 0;bottom: 0;left: 0;right: 0;background-color: rgb(68, 68, 68); opacity: 0.001; cursor: auto; z-index: 100002;"></div>').appendTo('#mainContainer');
						$('<div class="bodyMasker" style="position: absolute;top: 0;bottom: 0;left: 0;right: 0;background-color: rgb(68, 68, 68); opacity: 0.001; cursor: auto; z-index: 100002;"></div>').appendTo('#chatPanel');
					},
					endMove : function() {
						$('#mainContainer .bodyMasker').remove();
						$('#chatPanel .bodyMasker').remove();
					}
				});
			}
			if (splitter.dockState)
				$('i', switcher).removeClass('fa-angle-double-right').addClass('fa-comments-o');
			else
				$('i', switcher).removeClass('fa-comments-o').addClass('fa-angle-double-right');
		},

		registerHotkey : function(instance, key, callback) {
			var keyReg = hotkeys[key];
			if (!keyReg) {
				keyReg = hotkeys[key] = {};
				// console.log('Register hotkey: ' + key);
				$.hotkey(key, function() {
					// console.log('侦测到键盘事件: ' + key);
					var listener = hotkeys[key];
					for (var id in listener) {
						if (listener.hasOwnProperty(id)) {
							$.each(listener[id], function(i, cb) {
								cb();
							})
						}
					}
				})
			}
			keyReg[instance.id] = keyReg[instance.id] || [];
			keyReg[instance.id].push(callback);
		},

		unregisterHotkey : function(instance) {
			$F.log('Elite', '移除键盘监听者: ' + instance.id);
			for (var key in hotkeys) {
				if (hotkeys.hasOwnProperty(key)) {
					delete hotkeys[key][instance.id];
				}
			}
		},

		showHideSoftphone: function(show) {
			if (show) {
				$('#c_softphone').show();
			} else {
				$('#c_softphone').hide();
			}
		},

		logout: function() {
			window.onbeforeunload = false;
			$.cookie("remember_auto_login", null);
			$.cookie("remember_password", null);
			if ($E.softphone) {
				$E.softphone.quit(function() {
					$F.log('Elite', '注销系统 - 软电话发起回调');
					location.href = $E.url + "/logout?e=positive1";
				});
				/*
                //如果处于某种原因softphone.quit没有正常回调，则1.5秒后也执行退出
                setTimeout(function() {
                    $F.log('Elite', '注销系统 - 忽略软电话状态');
                    location.href = $E.url + "/logout?e=positive2";
                }, 1500);
                */
			} else {
				$F.log('Elite', '注销系统 - 主动发起');
				location.href = $E.url + "/logout?e=positive";
			}
		},

		Global: {
			checkCache: function(cacheKey) {
				return new Promise(resolve => {
					if ($E.query === 'mf') { // 只有微前端模式下走sessionStorage
						let value = sessionStorage.getItem(cacheKey);
						resolve(value);
					} else {
						resolve();
					}
				});
			},

			saveCache: function(cacheKey, cacheValue) {
				if ($E.query === 'mf') {
					if (typeof(cacheValue) ===  "object") {
						cacheValue = JSON.stringify(cacheValue);
					}
					sessionStorage.setItem(cacheKey, cacheValue)
				}
			}
		}

	};
	window.$E = $E;

	var hotkeys = {};
	var init = function() {
		// FIXED: by kevin, modified at 2017/03/09
		// 框架mode入参调整，增加更多模式
		// 0: 默认
		// 1：关闭websocket
		// 2：关闭websocket且不打开客户资料画面
		// 3: 关闭websocket，且不打开任何startup页面
		// 21: 不打开客户资料
		// 31: 不打开任何startup页面
		// 41： 使用无控件版本软电话，不去连接localproxy（默认是localproxy版）
		// 42: 使用无控件版本软电话，同时去连接localproxy
		$E.mode = parseInt($E.mode);
		$E.rsaPubKey = $('input#rsaPubKey').val();
		$E.currencyStyle = false;
		if (!$E.worker) {
			$E.worker = new Worker($E.url + '/js/elite.worker' + $E.jsv + '.js');
		}

		if (isNaN($E.mode))
			$E.mode = 0;

		if (!$E.query || $E.query === 'sp' || $E.query === 'cti')
			$('header').addClass('cti');

		if ($E.WebNotification && $E.WebNotification.permission !== "granted") {
			$E.WebNotification.requestPermission();
		}
		_mt.doms = new Date();
		if ($E.debug)
			console.info('Document on ready, took time: ' + (_mt.doms - _mt.begin) + '\'ms');

		require([ 'js/project' + $E.jsv,
				'js/websocketFactory' + $E.jsv,
				'js/dyn' + $E.jsv,
				'js/events' + $E.jsv,
				'js/constants' + $E.jsv,
				'js/lib/async.min',
				'js/softphone' + $E.jsv,
				'js/workorder' + $E.jsv,
				'js/workorder3' + $E.jsv,
				'js/cmdlib/generic' + $E.jsv,
				'js/cmdlib/advlib' + $E.jsv,
				'js/cmdlib/merge' + $E.jsv,
				'js/cmdlib/cti' + $E.jsv ],
			function(Project, wsFactory, dyn, events, constants, async, softphone, workorder, workorder3, generic, advlib, merge, cti) {
				window.$wsFactory = wsFactory;
				window.$D = dyn;
				window.$CONST = constants;
				window.$W = workorder;
				window.$W3 = workorder3;

				if ($E.query !== 'portal' && $E.query !== 'woa' && $E.query !== 'crm' && $E.query !== 'emb' && $E.query !== 'mf')
					$E.softphone = softphone.getInstance();

				$E.events = events.create();
				if ($PublicFun) {
					$PublicFun.$LIB = generic;
					$PublicFun.$ADVLIB = advlib;
					$PublicFun.$CTI = cti;
					$PublicFun.$MERGE = merge;
				} else
					$F.alert('严重错误，框架资源加载失败');

				_mt.resources = new Date();
				if ($E.debug)
					console.info('Required resource load completed, took time: ' + (_mt.resources - _mt.doms) + '\'ms');
				$F.log('Elite - initialize', $E.staff.id + '于[' + new Date().format('yyyy-MM-dd HH:mm:ss') + ']登录系统，开始初始化');
				initScreen();

				var asyncJob = [];
				asyncJob.push(function(callback) {
					initWebsocket(function() {
						callback(null, 'websocket');
					})
				});
				asyncJob.push(function(callback) {
					initStorage(function() {
						callback(null, 'storage')
					});
				});
				asyncJob.push(function(callback) {
					initLiveCheck(function() {
						callback(null, 'liveCheck');
					})
				});
				asyncJob.push(function(callback) {
					initSessionCheck(function() {
						callback(null, 'sessionCheck');
					})
				});
				// asyncJob.push(function(callback) {
				// 	// 这个加载了啥？
				// 	loadPublishCache(function() {
				// 		callback(null, 'loadPublishCache');
				// 	})
				// });
				asyncJob.push(function(callback) {
					loadCurrencyStyle(function() {
						callback(null, 'loadCurrencyStyle');
					})
				});

				// 初始化多项目
				$.each($E.staff.projects, function(i, v) {
					// console.log(v);
					v.id = v.id.trim();
					if (v.id == $E.staff.curProject)
						$E.staff.current = v;

					var project = Project.create(v.id, v.name, v.token, v.ordIndex, v.groupId, v.groupName, v.roles);
					if (i == 0)
						project.active(true);
					project.init(asyncJob);
					$E.projects[v.id] = project;
				});

				// 初始化软电话 需要用到项目系统参数，所以要再项目初始化之后再初始化电话
				if ($E.softphone) {
					asyncJob.push(function(callback) {
						$E.softphone.init();
						var proj = $E.getActiveProject();
						$E.softphone.callSoftphoneLoginInfo(proj);
						$E.softphone.setJSService(proj);
						$E.events.register($CONST.EVENT.PROJECT_CHANGED, 'Softphone', function(data) {
							var proj = $E.projects[data.id];
							if (proj) {
								$E.softphone.callSoftphoneLoginInfo(proj);
								$E.softphone.setJSService(proj);
								$E.softphone.simpleCommonCall('changeproject', 'ProjectId=' + proj.id);
							}
						});
						let interval = $F.parseInt(proj.getParam('STKIVL'));
						if (interval > 0) {
							// 开启token检查，如果发现已经失效，则调用软电话的登出
							$E.softphone.startTokenCheck({
								interval: Math.max(interval, 5000), // 最小配置5秒一次
								onFail: function() {
									$E.softphone.quit(function() {
										$F.log('Elite', '注销系统 - 软电话发起回调');
										location.href = $E.url + "/logout?e=tokenCheck";
									});
								}
							});
						}
						callback(null, 'softphone');
					});
				}

				$E.async = async;
				if ($E.debug)
					console.info('Start async initializing...');
				$E.async.series(asyncJob, function(err, results) {
					_mt.initialized = new Date();
					if ($E.debug) {
						if (H5Utils.isChrome)
							console.log('%c初始化系统完毕，耗时：' + (_mt.initialized - _mt.begin) + '\'ms', " color:#197b02; text-shadow: 0 1px 0 #ccc,0 2px 0 #c9c9c9,0 3px 0 #bbb,0 4px 0 #b9b9b9,0 5px 0 #aaa,0 6px 1px rgba(0,0,0,.1),0 0 5px rgba(0,0,0,.1),0 1px 3px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2),0 5px 10px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.2),0 20px 20px rgba(0,0,0,.15);font-size:3em");
						else
							console.log('初始化系统完毕，耗时：' + (_mt.initialized - _mt.begin) + '\'ms');
					}
					setTimeout(function() {
						for (var id in $E.projects) {
							$E.projects[id].start();
						}
						if ($E.query !== 'emb' && $E.query !== 'portal' && $E.query !== 'mf') {
							// 默认风格
							const mainContainer = $("#mainContainer");
							if ($('#body').hasClass('twocol')) {
								$('#sideBar').show();
								mainContainer.addClass('collapsed')
							} else {
								mainContainer.wisSplitter({
									direct : 'h',
									cookie : 'splitter.main',
									fixedSize: 240,
									minSize : 200,
									maxSize : 400,
									handleGrab : true,
									dockable : 3
								})
								$E.menuHide = $.cookieBoolean('system.menuHide', false);
								if ($E.menuHide) {
									$('#sideBar').toggle(! $E.menuHide);
									mainContainer.toggleClass('slideMenu', $E.menuHide);
									$('#menuBar a.trigger').toggleClass('pin', !$E.menuHide);
								}
								$('#menuBar a.trigger').on('click', function(e) {
									e.preventDefault();
									$E.menuHide = !$E.menuHide;
									$.cookie('system.menuHide', $E.menuHide, {expired: 30});
									$('#sideBar').toggle(! $E.menuHide);
									mainContainer.toggleClass('slideMenu', $E.menuHide);
									$('#menuBar a.trigger').toggleClass('pin', !$E.menuHide);
								})
							}
						}

						setUI()

						// //初始化自動鎖屏s
						let screenStatus = localStorage.getItem('screenStatus')
						if(screenStatus == '1'){
							$E.getActiveProject().lockScreen();
						}else {
							$F.lockScreenTimer();
						}
						if ($E.query !== 'emb' && $E.query !== 'portal' && $E.query !== 'woa' && $E.query !== 'mf')
							openNotification();

						const proj = $E.getActiveProject();
						if ($E.jsv) {
							// 创建活动检测(AFK)，仅当PORTAL, CRM和WOA模式下有效
							// debug模式关闭AFK检查
							if ($E.query === 'portal' || $E.query === 'woa' || $E.query === 'crm' || proj.getParam('ENAAFK')) {
								$F.log('Elite', '设置AFK超时限制：' + $E.afkTime + '秒');
								$(document).on('click', function(e) {
									$E.live = new Date().getTime();
								});
								$(document).on('keydown', function(e) {
									$E.live = new Date().getTime();
								});
								setInterval(function() {
									let afk = new Date().getTime() - $E.live;
									let reload = false;
									if (afk > $E.afkTime * 1000) {
										if ($E.query === 'portal' || $E.query === 'woa' || $E.query === 'crm') {
											reload = true;
										} else {
											if ($E.softphone && !$E.softphone.isCallBusy() && !$E.softphone.isACW()) {
												reload = true;
											}
										}
										if (reload) {
											$F.err('Elite', $F.lang('afkNotify').format($E.afkTime, new Date($E.live).format('yyyy-MM-dd hh:mm:ss')));
											window.onbeforeunload = false;
											location.href = $E.url + ($E.query === 'portal' ? '/portal' : '') + '/logout?e=afk';
										}
									}
								}, 1000);
							}
						}
						if ($E.query === 'emb' || $E.query === 'mf') {
							//console.log('正在加载客户资料');
							proj.customer.generateByGuid($E.customerGuid || '1                                   ');
							if ($E.addinType === 'obj') {
								//console.log('正在打开市场活动');
								proj.openAddinObjByOtId('AddinOBJ', '', $E.addinId, $E.parameters, true);
							} else if ($E.addinType === 'wo') {
								//console.log('正在打开工单资料');
								proj.openAddinWOByOId('AddinWOrder', '', $E.addinId, $E.parameters, true);
							} else if ($E.addinType === 'wo3') {
								var taskId = $E.parameters['f1'];
								var readonly = $E.parameters['f2'];
								//console.log('正在打开工单3 - oId:' + $E.addinId + '  taskId: ' + taskId);
								proj.openAddinWO3ByOId('ADDINWO3', '', $E.addinId, taskId, $E.parameters, undefined, undefined, readonly);
							} else if ($E.addinType === 'plugin') {
								var addin = proj.getAddin($E.addinId);
								if (!addin) {
									$F.err('不存在的插件：' + $E.addinId);
								} else {
									//console.log('正在打开插件', addin);
									proj.openAddinPlugin(addin.name, addin, $E.addinParam, $E.parameters, true);
								}
							} else {
								if ($E.addinId) {
									//console.log('正在打开动态页面');
									proj.openAddinDyn($E.addinId, '', $E.parameters, true, $E.addinType.toUpperCase(), $E.addinType.toUpperCase() === 'DYN2');
								}
							}
						} else if ($E.query === 'portal') {
							// 打开PORTAL首页
							//console.log('打开默认系统首页：' + $E.sbcust)
							$("#sideBar").hide();
							if ($E.sbcust) {
								proj.openAddinDyn($E.sbcust, '', $E.parameters, true, $E.dynVer, $E.dynVer.toUpperCase() === 'DYN2')
							}
						}
						if (proj.getParam('WTMARK')) {
							var args = proj.getParam('WTMARK');
							var date = new Date($F.getDbTime());
							$E.staff.name = $E.staff.name.replace(/[\r\n\t]/g,"");

							var argsJson = JSON.parse(args);

							var argsArr = argsJson.watermark_txt.split('$');
							var newStr = '';
							argsArr.map(i => {
								var str = i;
								if(i.indexOf('{') > -1) {
									var narr = i.split('}');
									var nstr = narr[0].substring(1);

									if (nstr.indexOf('.') > -1) {
										var nsArr = nstr.split('.');
										if(nsArr.length == 2) {
											if(nsArr[0] === 'date') {
												str = date.format(nsArr[1]) + narr[1];
											} else
												str = ($E.staff[nsArr[0]] && $E.staff[nsArr[0]][nsArr[1]]) ? ($E.staff[nsArr[0]][nsArr[1]]  + narr[1]) : narr[1]
										} else {
											$F.notify('不符合规范的写法');
										}
									} else if($E.staff[nstr])
										str = $E.staff[nstr]  + narr[1];
									else
										str = narr[1]
								}
								newStr = newStr + str;
							})

							argsJson.watermark_txt = newStr;

							require(['js/amds/effects' + $E.jsv], function(Effects) {
								return Effects.watermark(argsJson);
							})
						}
					}, 10)
				})

			})
	};

	// UI展示参数设置
	setUI  = function () {
		const proj = $E.getActiveProject();
		let uiParams = proj.getParam('UICFGP');
		console.log('UICFGP', uiParams)
		try{
			uiParams = JSON.parse(uiParams);
		} catch (e) {
			console.log(e)
		}
		if (typeof uiParams === 'undefined' || uiParams === '') {
		} else {
			!uiParams.message.visible && $("#uicfgMessageSwitch").hide();
			if (!uiParams.quickMenu.visible) {
				$("#uicfgQuickMenuSwitch").hide();
				$("#launcherBtn").hide();
			}
			!uiParams.menu.visible && $("#uicfgMenuSwitch").hide();
			!uiParams.theme.visible && $("#themeChange").hide();
			if (!uiParams.message.visible && !uiParams.quickMenu.visible && !uiParams.menu.visible && !uiParams.theme.visible) {
				$("#uicfgBtn").hide();
			}
			$E.sysactSlideout = uiParams.message.value;
			if ($E.sysactSlideout)
				$.cookie('system.sysactSlideout', '1', {expires:30});
			else
				$.cookie('system.sysactSlideout', null);
			$E.shortcutsHide = !uiParams.quickMenu.value;
			if ($E.shortcutsHide)
				$.cookie('system.shortcutsHide', '1', {expires:30});
			else
				$.cookie('system.shortcutsHide', null);
			$E.menuHide = !uiParams.menu.value;
			$.cookie('system.menuHide', $E.menuHide, {expires:30});
			$('body').toggleClass('hideShortcuts', $E.shortcutsHide);
			$('#sideBar').toggle(! $E.menuHide);
			$("#mainContainer").toggleClass('slideMenu', $E.menuHide);
			$('#menuBar a.trigger').toggleClass('pin', !$E.menuHide);
			registerMessageActionE()
		}
	}

	var registerMessageActionE;

	/*
   * 初始化框架元素
   */
	var initScreen = function() {
			// 初始化登录计时器
			var sc = new Date();
			var refreshLoginTime = function() {
				var s = (new Date() - sc) / 1000;
				$("#login_timer .clock").text([ parseInt(s / 60 / 60), parseInt(s / 60 % 60), parseInt(s % 60) ].join(":").replace(/\b(\d)\b/g, "0$1"));
				setTimeout(refreshLoginTime, 1000);
			};
			refreshLoginTime();

			if ($E.query !== 'emb' && $E.query !== 'mf') {
				$(window).focus(function() {
					$E.windowOnFocus = true;
				});
				$(window).blur(function() {
					$E.windowOnFocus = false;
				});
				window.onbeforeunload = function() {
					return $F.lang('ui.reload');
				};
			}
			window.onunload = function() {
				// 浏览器关闭时，通知所有项目关闭
				for (var key in $E.projects) {
					$E.projects[key].destroy();
				}
				if ($E.softphone) {
					$E.softphone.quit();
				}
				if ($E.worker) {
					$E.worker.terminate();
				}
				if ($E.jsv && $E.query !== 'emb' && $E.query !== 'mf') {
					$F.log('Elite', '浏览器主动发起登出请求');
					$.post($E.url + ($E.query === 'portal' ? '/portal' : '') + "/logout_?e=onunload&w=" + (!!$E.softphone));
				}
			};

			$('#main_fullscreen_logo').on('click', function(e) {
				H5Utils.fullscreen($('body'))
			})

			// 注册消息列表滑块
			var registerMessageAction = function() {
				$("header .c_alert").off('mouseenter').off('mouseleave');
				$("header .c_alert>a").off('click');
				if ($E.sysactSlideout) {
					$("header .c_alert").hover(function() {
						$("header .c_tools>a").removeClass('selected');
						$("header #c_tools").animate( { height: "hide" }, 100 );
						$("header .c_me>a").removeClass('selected');
						$("header #c_user").animate( { height: "hide" }, 100 )

						$("header .c_alert>a").addClass('selected');
						$("header #c_alert").show();
					}, function() {
						$("header .c_alert>a").removeClass('selected');
						$("header #c_alert").animate( { height: "hide" }, 100 );
					})
				} else {
					$("header .c_alert>a").on('click', function() {
						$("header .c_alert>a").addClass('selected');
						$("header #c_alert").show();
					}).clickOff(function() {
						$("header .c_alert>a").removeClass('selected');
						$("header #c_alert").animate( { height: "hide" }, 100 );
					})
				}
			}

			registerMessageActionE = registerMessageAction;

			// 更新用户账号信息
			if ($E.staff.name == '##CT##' || $E.staff.name == '######') {
				$('header .c_me').remove();
				$('header .c_tools').remove();
			} else {
				$('header .c_me .c_me_name').text($E.staff.name);
				$('header .c_me .c_me_loginName').text($E.staff.loginName);
				$('header .c_me .js_dbpool').text($E.dataService.dbPool);
				if ($E.staff.headImg) {
					var cusImg = new Image();
					cusImg.src = $E.url + '/fs/get?file=' + $E.staff.headImg;
					$(cusImg).on('load', function() {
						$('header img.c_me_pic').attr('src', this.src);
					})
				}

				$E.sysactSlideout = $.cookieBoolean('system.sysactSlideout', false);
				// 注册用户信息滑块
				$("header .c_me>a").on('click', function() {
					$("header .c_me>a").addClass('selected');
					$("header #c_user").show();
				}).clickOff(function() {
					$("header .c_me>a").removeClass('selected');
					$("header #c_user").animate( { height: "hide" }, 100 )
				});
				// 注册“修改头像”按钮
				$("header #c_user .headimg").click(function(e) {
					e.preventDefault();
					$E.headImg();
				});
				// 注册“修改密码”按钮
				$("header .c_right .password").click(function(e) {
					e.preventDefault();
					$E.pwdChange();
				});

				// 注册“切换用户组”按钮
				$("header #c_user .changegrp").click(function(e) {
					e.preventDefault();
					$E.grpChange();
				});
				// 注册“管理台”按钮
				$("header #c_user .admin").click(function(e) {
					var url = $E.url + '/admin/login',
						params = [];
					if ($E.dataService.key !== 'default')
						params.push('ds=' + $E.dataService.key);
					if (!$E.jsv)
						params.push('dev=true');
					if (params.length > 0)
						url += '?' + params.join('&');
					window.open(url, 'elite.admin');
				});
				// 注册“注销”按钮
				$("header .logout").click(function(e) {
					$F.confirm($F.lang('sys.logout'), function() {
						$E.logout();
					})
				});
				registerMessageAction();
				$('header #c_alert>li.notes>a').on('click', function() {
					$E.openPlugin($F.lang('plugin.message'), $E.getActiveProject(), 'message', 'note');
				})

				// 注册系统信息滑块
				$("header .c_tools>a").on('click', function(){
					$("header .c_tools>a").addClass('selected');
					$("header #c_tools").show();
				}).clickOff(function() {
					$("header .c_tools>a").removeClass('selected');
					$("header #c_tools").animate( { height: "hide" }, 100 );
				});
				// 配置页面快捷菜单
				$("header #c_tools .launcher").click(function(e) {
					$("header #c_tools").hide();
					$E.getActiveProject().onLauncher();
				});
				// 关闭当前项目所有tab页
				$("header #c_tools .close_all_tabs").click(function(e) {
					$("header #c_tools").hide();
					$E.getActiveProject().tabCloseAll();
				});
				// 清除当前页面结构缓存--开发调试用
				$("header #c_tools .clear_all_structs").click(function(e) {
					$("header #c_tools").hide();
					$D.structs = {};
					var project = $E.getActiveProject();
					project.cache = {};
					project.globalcmds = {};
					project.initCache(function(){
						project.initDbMask();
					});
					$F.notify($F.lang('ui.cfg.clearCaches'));
				});
				//锁屏
				$("header #c_tools .lock_screen").click(function(e) {
					$("header #c_tools").hide();
					$E.getActiveProject().lockScreen();
				});
				$("#lockScreen .close").click(function(e) {
					$E.getActiveProject().hideLockScreen();
				});
				$("#lockScreen #checkPass").focus(function(e) {
					$('#lockScreen .errorTip').html('');
				});
				// 创建多项目切换
				$("header #c_tools .proj_switch").click(function(e) {
					e.preventDefault();
					var projId = $(e.target).attr("data-id");
					for (var key in $E.projects) {
						if (key !== projId) {
							$E.projects[key].active(false);
						}
					}
					$E.projects[projId].active(true);
					$E.events.notify($CONST.EVENT.PROJECT_CHANGED, {
						id : projId
					});
					$("header .c_me_proj").text('@' + $E.projects[projId].name);
				})

				$E.tabDir = $.cookie('system.tabDir') || '';
				$E.theme = $.cookie('system.theme') || $E.theme;
				$E.shortcutsHide = $.cookieBoolean('system.shortcutsHide',  false);
				$E.menuHidden = $.cookieBoolean('system.menuHide', false);
				//切换UI样式
				$('header a.uicfg').click(function(e) {
					e.preventDefault();
					var dialog = $('#uicfgDialog'), sysactSwitch, shortcutsSwitch, menuSwitch;
					$F.dialogOpen(dialog, {
						onOpen : function() {
							sysactSwitch = $('span.js_sysact', dialog).wisSwitch({
								width: 100,
								bgColor: {
									on: '#6eae8c',
									off: 'red'
								},
								offTip: $F.lang('ui.cfg.msgalt.off'),
								onTip: $F.lang('ui.cfg.msgalt.on')
							}).val($E.sysactSlideout);
							shortcutsSwitch = $('span.js_shortcuts', dialog).wisSwitch({
								width: 100,
								bgColor: {
									on: '#6eae8c',
									off: 'red'
								},
								offTip: $F.lang('generic.hide'),
								onTip: $F.lang('generic.show')
							}).val(!$E.shortcutsHide);
							menuSwitch = $('span.js_menu', dialog).wisSwitch({
								width: 100,
								bgColor: {
									on: '#6eae8c',
									off: 'red'
								},
								offTip: $F.lang('generic.hide'),
								onTip: $F.lang('generic.show')
							}).val(!$E.menuHide);
							$E.getSysTheme();
							$('select[name=tabDir]', dialog).val($E.tabDir);
							$('select[name=theme]', dialog).val($E.theme);
						},
						onSubmit : function() {
							var tabDir = $('select[name=tabDir]', dialog).val(),
								theme = $('select[name=theme]', dialog).val();
							// shortcuts configuration
							$E.shortcutsHide = !shortcutsSwitch.val();
							if ($E.shortcutsHide)
								$.cookie('system.shortcutsHide', '1', {expires:30});
							else
								$.cookie('system.shortcutsHide', null);
							$('body').toggleClass('hideShortcuts', $E.shortcutsHide);
							// menu hidden configuration
							$E.menuHide = !menuSwitch.val();
							$.cookie('system.menuHide', $E.menuHide, {expires:30});
							var trigger = $('#menuBar a.trigger');
							$('#sideBar').toggle(! $E.menuHide);
							$("#mainContainer").toggleClass('slideMenu', $E.menuHide);
							$('#menuBar a.trigger').toggleClass('pin', !$E.menuHide);
							// system message action slide out configuration
							$E.sysactSlideout = sysactSwitch.val();
							if ($E.sysactSlideout)
								$.cookie('system.sysactSlideout', '1', {expires:30});
							else
								$.cookie('system.sysactSlideout', null);
							registerMessageAction();

							if (tabDir !== $E.tabDir) {
								if (tabDir)
									$.cookie('system.tabDir', tabDir, {expires:tabDir});
								else
									$.cookie('system.tabDir', null);
								if ($E.tabDir)
									$('body').removeClass($E.tabDir);
								$('body').addClass(tabDir);
								$E.tabDir = tabDir;
							}
							if (theme !== $E.theme) {
								$F.confirm($F.lang('ui.cfg.themesChanged'), function() {
									$F.dialogClose(dialog);
									window.onbeforeunload = false;
									$E.jsv = '';
									if (theme)
										$.cookie('system.theme', theme, {expires:theme});
									else
										$.cookie('system.theme', null);
									window.location.reload(true);
								});
							}

							$F.dialogClose(dialog);
						}
					});
				});

				// 注册软电话TIP
				if ($E.softphone) {
					$("header #c_softphone").tooltip({
						position : {
							my : "left top",
							at : "left bottom+5"
						},
						close : function() {
							$('.ui-helper-hidden-accessible').remove();
						},
						tooltipClass : 'sp-tooltip'
					});
				}

				if ($E.query !== 'emb' && $E.query !== 'portal' && $E.query !== 'woa' && $E.query !== 'mf') {
					initHotkeys();
				}

				if ($E.query == 'portal') {
					// 注册“注销”按钮
					$("header .logout").click(function(e) {
						$F.confirm($F.lang('sys.logout'), function() {
							window.onbeforeunload = false;
							$.cookie("remember_auto_login", null);
							$.cookie("remember_password", null);
							$F.log('Elite', '注销系统 - 主动发起');
							location.href = $E.url + "/portal/logout?e=positive";
						})
					});
				}

			}
			// return registerMessageAction()
			// fixed by kevin, language parameter get from session
			//$E.lang = $.cookie('language') || 'zh_CN';
		},


		isCTIMode = function() {
			return ($E.mode == 0 || $E.mode >= 10) && $E.query !== 'emb' && $E.query !== 'mf';
		},
		/*
     * 初始化WebSocket
     */
		initWebsocket = function(callback) {
			var waterfalls = [];
			// initialize local-proxy websocket
			if (($E.mode > 0 && $E.mode < 10 ) || $E.query === 'emb' || $E.mode === 99 || $E.query === 'mf') {
				$F.log('Elite', "启动无控件模式");
			} else {
				if ($E.mode === 41) { // 41 不启动localproxy， 42 启动localproxy
					$F.log('Elite', "无控件模式不开启本地WebSocket");
				} else {
					waterfalls.push(function(callback){
						$wsFactory($E.ws.local.address, function(ws) {
							// on open
							ws.send(JSON.stringify({
								"module" : "upgrade",
								"content" : new Date().format()
							}))
							$E.ws.local.proxy = ws;
							$F.log('Elite - initWebsocket', 'LocalProxy WebSocket连接成功');
						}, function(ws) {
							// on close
							delete $E.ws.local.proxy;
						}, function(e) {
							$E.ws.local.eventHandle(e);
						}, callback);
					})
				}
			}
			// initialize workload websocket
			if ($E.agentMonitor) {
				initWorkload();
				if (isCTIMode()) {
					waterfalls.push(function(callback) {
						$wsFactory($E.ws.workload.address, function(ws) {
							// on open
							$E.ws.workload.proxy = ws;
							$F.log('Elite - initWebsocket', 'WorkloadNotify WebSocket连接成功');
						}, function(ws) {
							// on close
							delete $E.ws.workload.proxy;
						}, function(e) {
							// on received
							processWorkload(e);
							//console.log('AgentInfo: ', info);
						}, callback);
					})
				}
			}
			// initialize framework websocket
			waterfalls.push(function(callback) {
				$wsFactory($E.ws.framework.address, function(ws) {
					// on open
					$E.ws.framework.proxy = ws;
					$F.log('Elite - initWebsocket', 'Framework WebSocket连接成功');
					$('footer .f_heart>i.js_socketSuccessed').show();
					$('footer .f_heart>i.js_socketFaild').hide();
				}, function(ws) {
					// on close
					delete $E.ws.framework.proxy;
					$('footer .f_heart>i.js_socketSuccessed').hide();
					$('footer .f_heart>i.js_socketFaild').show();
				}, function(e) {
					if (e.module !== 'heartbeat')
						$E.ws.framework.eventHandle(e);
				}, callback);
			})
			$E.async.waterfall(waterfalls, function (err, result) {
				callback();
			})
		},

		initStorage = function(callback) {
			if (sessionStorage.getItem($CONST.CacheName.PUBLIC_CACHE) == null) {
				var mt = new Date();
				$F.dataService('SystemDo2', {
					data : $F.sqlbean('System.cache.get', $E.staff.projects[0].token, [ $E.staff.id, 'PUBLIC' ]),
					digest : $E.staff.projects[0].ordIndex,
					success : function(data) {
						if (data.code < 0) {
							$F.err('Elite - initStorage', data.message);
						} else {
							if (data.value[0].count < 0)
								$F.err('Elite - initStorage', $F.lang('db.error') + data.value[0].key);else {
								var cs = {};
								$.each(data.value[0].fields, function(i, v) {
									cs[v[0]] = v[1];
								});
								sessionStorage.setItem($CONST.CacheName.PUBLIC_CACHE, JSON.stringify(cs));
							}
						}
						$F.log('Elite - initStorage', '读取系统个性化公共数据完成, took time: ' + (new Date() - mt) + '\'ms', cs)
					},
					always : function() {
						callback();
					}
				})
			} else {
				$F.nextTick(callback);
			}
		},

		/*
     * 注册客户端心跳检测
     */
		initLiveCheck = function(callback) {
			$F.log('Elite', 'Start live check deamon');

			$.each($E.staff.projects, function() {
				var proj = this,
					icon = $('footer .f_heart>i.js_heartbeat'),
					lc = function() {
						$F.log('Elite', 'process live check for: ' + proj.name);
						$F.dataService('StaffCheck', {
							data : {
								time : new Date(),
								token : proj.token
							},
							digest: proj.ordIndex,
							success : function(data) {
								if (data.code > 0) {
									icon.removeClass('warn').attr('title', $F.lang('ui.livesuccess'));
									// setTimeout(function() {
									// 	lc();
									// }, 1000 * 60 * 10);
									$E.worker.postMessage({
										cmd: 'liveCheck',
										timeout: 1000 * 60 * 10
									});
								} else {
									icon.addClass('warn').attr('title', $F.lang('ui.liveerror'));
									// 检查失败直接自动退出
									$F.err('Elite', 'StaffCheck失败，自动退出');
									window.onbeforeunload = false;
									if ($E.softphone) {
										$E.softphone.quit();
									}
									setTimeout(function(){
										location.href = $E.url + ($E.query === 'portal' ? '/portal' : '') + '/logout?e=positive2';
									}, 1500);
								}
							},
							fail : function() {
								icon.addClass('warn').attr('title', $F.lang('ui.liveerror'));
								// setTimeout(function() {
								// 	lc();
								// }, 1000 * 30);
								$E.worker.postMessage({
									cmd: 'liveCheck',
									timeout: 1000 * 30
								});
							},
							silent : true
						});
					};

				$E.worker.addEventListener('message', e => {
					if (e.data.action === 'liveCheck') {
						lc();
					}
				}, false);

				lc();
			});
			callback();
		},

		/*
     * 注册客户端心跳检测
     */
		initSessionCheck = function(callback) {
			$F.log('Elite', 'Start session keeping deamon');
			var query = $E.url + '/login',
				params = [];
			if (!$E.jsv)
				params.push('dev=true');
			if ($E.dataService.key !== 'default')
				params.push('ds=' + $E.dataService.key);
			if ($E.mode)
				params.push('mode=' + $E.mode);
			if (params.length > 0)
				query = query + '?' + params.join('&');

			var lc = function() {
				$F.log('Elite', 'Process session keeping');
				$.ajax({
					type : 'post',
					url : $E.url + '/help/keeping/client',
					data : {
						t : new Date().getTime()
					}
				}).done(function(data) {
					if (data.code > 0) {
						$F.log('Elite', 'Session keep success');
						$E.worker.postMessage({
							cmd: 'sessionCheck',
							timeout: 1000 * 60 * 10
						});
						// setTimeout(function() {
						// 	lc();
						// }, 1000 * 60 * 10);
					} else
						$F.alert(data.message, function() {
							window.onbeforeunload = false;
							location.href = query;
						});
				}).fail(function(jqXHR) {
					$F.err('Elite', Ajax.getFailed(jqXHR));
					$E.worker.postMessage({
						cmd: 'sessionCheck',
						timeout: 1000 * 60
					});
					// setTimeout(function() {
					// 	lc();
					// }, 1000 * 60);
				})
			};

			$E.worker.addEventListener('message', function(e) {
				if (e.data.action === 'sessionCheck') {
					lc();
				}
			}, false);

			lc();
			callback();
		},

		loadPublishCache = function(callback) {
			var project = $E.staff.projects[0];
			$F.ngsService({
				url: $E.url + ($E.query === 'portal'? '/portal' : '') + '/publishCaches_',
				data: {
					version: $E.publishVersion
				},
				success: function(data) {
					if (data.code > 0) {
						if ($E.debug)
							console.info('Publish version cache: ', data.value);
					} else {
						$F.err(data.message);
					}
				},
				always: function() {
					callback();
				}
			}, project.token, project.ordIndex);
		},

		loadCurrencyStyle = function(callback) {
			$E.Global.checkCache("ngs.currencyStyle").then(ret => {
				if (ret !== null) {
					$E.currencyStyle = (ret === 'true');
				} else {
					Ajax.get({
						url: $E.url + "/currencyStyle.json",
						async: false,
						success: function(data) {
							$E.currencyStyle = data.contains($E.lang);
							$E.Global.saveCache("ngs.currencyStyle", $E.currencyStyle);
						}
					});
				}
				callback();
			});
		},

		initHotkeys = function() {
			// 创建快捷键
			var f9Ask = false;
			$.hotkey('f9', function(e) {
				if (!f9Ask) {
					f9Ask = true;
					$F.confirm($F.lang('sys.reloadConfirm'), function() {
						window.onbeforeunload = false;
						$E.jsv = '';
						window.location.reload(true);
					}, function() {
						f9Ask = false;
					})
				}
			})

			$.hotkey('f4', function() {
				if (window.onbeforeunload) {
					window.onbeforeunload = false;
					f9Ask = true;
					$F.info('已经页面关闭离开事件，现在可以重载页面')
				}
			})

			if ($E.softphone) {
				$.hotkey('f3', function() {

					$F.log('Hotkey Click', 'Hotkey F3');

					$F.confirm('确定强制结束语音平台工作状态(结束后电话将变成就绪状态)?', function() {
					    $F.log('Hotkey Confirm', 'Hotkey F3');
                        $SC.notifyWorkEnd();
                        $E.getActiveProject().workDuration=false;
					}, function() {
						$F.log('Hotkey Cancel', 'Hotkey F3');
					})
				})
			}

			$.hotkey('alt+c', function() {
				$E.getActiveProject().tabCloseAll();
			})

			$.hotkey('alt+r', function() {
				if (!$E.debug) return
				$D.structs = {};
				var project = $E.getActiveProject();
				project.cache = {};
				project.globalcmds = {};
				project.initCache(function(){
					project.initDbMask();
				})
				if (!$E.dataService.saas || !$E.staff.epidDbPool) {
					project.objectiveTypes = [];
					project.initObjectiveTypes(function() {
						$F.log('Refresh cache', 'Refresh objectiveTypes successful');
					});
				}
				project.woFrameMaps = [];
				project.initWoFrameMaps(function(){
					$F.log('Refresh cache', 'Refresh woFrameMap successful');
				});
				$W3.Struct.clearStructCache();
				$F.notify($F.lang('ui.cfg.clearCaches'));
			})

			$.hotkey('ctrl+o', function() {
				verifyPwd2();
			})

			// $.hotkey('f10', function() {
			// 	$E.getActiveProject().lockScreen();
			// })

			// 初始化调试面板
			var con = $('#eliteConsole').hide();
			var test = function(execute) {
					if (! this.runtime)
						return;
					try {
						if (execute.startWith(':')) {
							execute = execute.substring(1);
							var cs = execute.split('.'),
								bean = {};
							if (cs[0] == 'var' || cs[0] == 'tabc')
								bean[execute] = this.runtime.data.local[cs[0]][cs[1]];
							else
								bean[execute] = this.runtime.data.pub[cs[0]][cs[1]];
							console.log(bean);
							return;
						} else
							eval('console.log(this.' + execute + ')');
					} catch (x) {
						console.error(x);
					}
				},
				make = function(t) {
					var proj = $E.getActiveProject(),
						active = proj.tabActived();
					if (! active.length) {
						$F.err('No page has opend!');
						return;
					}

					var instance = active.data("instance");
					var ev = {
						project : proj,
						structs : $D.structs[proj.id],
						events : proj.events,
						caches : proj.cache,
						instance : instance || {},
						runtime : (instance ? (instance.runtime || {}) : {}),
						components : CtlUtils.findAllComponents(instance.runtime)
					}
					test.call(ev, t);
				}
			$('input[name=execute]', con).on('keypress', function(e) {
				if (e.keyCode == 13) {
					var e$ = $(e.target),
						t = e$.val();
					make(t);
					e$.val('').focus();
				}
			}).on('keyup', function(e) {
				if (e.keyCode == 27) {
					Helper.masker.hide(con);
				}
			});
			$('.title>a', con).on('click', function(e) {
				e.preventDefault();
				Helper.masker.hide(con);
			})
			$('.content a', con).on('click', function(e) {
				e.preventDefault();
				make($(e.currentTarget).attr('data-value'));
			})
			con.draggable({
				handle : '.title'
			})
			$('body').css({
				'overflow-x' : 'auto',
				'overflow-y' : 'hidden'
			});
			var consoleShow = false;
			$.hotkey('f2', function() {
				if (!$E.debug) return
				if (!consoleShow) {
					consoleShow = true;
					Helper.masker.show(con, {
						onOpen : function() {
							$('input[name=execute]', con).val('').focus();
						},
						onClose : function() {
							consoleShow = false;
						}
					});
				}
			})
		},

		openNotification = function() {
			var nc = $.cookie('system.notify.check'),
				date = $.cookie('notification_rt_' + $E.dataService.key),
				project = $E.getActiveProject();
			$F.dataService('SystemDo2', {
				data : $F.sqlbean('System.notification.read', project.token, [ $E.staff.epid || '_MAIN_' ]),
				digest: project.digest,
				success : function(data) {
					// console.log(data);
					if (data.code > 0) {
						if (data.value[0].count > 0) {
							var content = data.value[0].fields[0][0],
								modifiedDate = data.value[0].fields[0][2];
							$.cookie('notification_rt_' + $E.dataService.key, modifiedDate, {
								expires : 30
							});
							//console.log(date);
							//console.log(modifiedDate);
							//console.log(nc)
							if ((!date || date < modifiedDate || !nc) && content !== '') {
								var div = $('<div style="" />').html(content);
								$F.createDialog(div, {
									icon : 'bell',
									title : $F.lang('notification.title'),
									closable : true,
									escapable : true,
									removable : true,
									contentCSS : {
										'padding' : '20px',
										'overflow' : 'auto',
										'minWidth' : '600px',
										'maxWidth' : '800px',
										'minHeight' : '300px',
										'maxHeight' : '500px'
									},
									preOpen : function() {
										$('.topIcon', this).css('color', 'red');
									},
									onOpen : function() {
										$('.exTitle', this).append('<label style="position:absolute;right:60px;font-size:12px"><input type="checkbox" id="js_noshow" />' + $F.lang('notification.hideflag') + '</label>');
										$('#js_noshow', this).prop('checked', (nc ? true : false))
									},
									onClose : function() {
										// console.error('close notification')
										if ($('#js_noshow', this).prop('checked')) {
											$.cookie('system.notify.check', 1, {
												expires : 30
											});
										} else
											$.cookie('system.notify.check', null);
									}
								});
							}
						}
					} else{
						$F.err('Elite - openNotification', data.message);
					}
				}
			})
		},

		verifyPwd2 = function() {
			if ($E.staff.lsa) {
				$F.confirm('Sign out living security authorization ?', function() {
					var project = $E.getActiveProject();
					$F.ngsService({
						url: $E.url + '/lsaout_',
						success: function(data) {
							delete $E.staff.lsa;
							$F.notify($F.lang('sys.lsa.out.success'));
						}
					}, project.token, project.digest)
				})
			} else {
				var dom = $('<div style="font-size:24pt;padding:10px"><input type="password" style="color:red;" /></div>');
				$F.createDialog(dom, {
					title: 'Live security authorition',
					removable: true,
					onOpen: function() {
						$('input', dom).focus();
					},
					onCancel: function(close) {
						close();
					},
					onSubmit: function(close) {
						var pwd2 = $('input[type=password]', dom).val();
						close();
						if (pwd2) {
							var project = $E.getActiveProject();
							$F.ngsService({
								url: $E.url + '/lsa_',
								data: {
									code: $F.encPwd(pwd2, $E),
									uid: $E.uid
								},
								success: function(data) {
									if (data.code > 0) {
										$E.staff.lsa = true;
										$F.notify($F.lang('sys.lsa.success'));
									} else {
										delete $E.staff.lsa;
										$F.notify($F.lang('sys.lsa.faild'), -1);
									}
								}
							}, project.token, project.digest)
						}
					}
				})
			}
		},

		initWorkload = function() {
			if (! $E.wlCfg) {
				var project = $E.getActiveProject();

				$E.staff.queues = $E.staff.queues || {};
				$E.staff.chatQueues = $E.staff.chatQueues || {};
				$E.wlCfg = $E.wlCfg || {};
				/*
					是否显示监控；
					滚屏间隔；
					阈值
					告警颜色
					非告警颜色
				*/
				var dataRequest = {
					token: project.token,
					dbPool: '',
					sqls: [{
						key: 'wl.cfg.getByStaffId',
						maxRow: 1
					}, {
						key: 'wl.cfg.getByGroupId',
						maxRow: 1
					}, {
						key: 'wl.cfg.getDefault',
						maxRow: 1
					}, {
						key: 'wl.dnlist'
					}, {
						key: 'wl.chat.waq'
					}]
				};
				var dnlist = {}, chatQueues = {};
				$F.dataService('SystemDo2', {
					data: dataRequest,
					digest: project.digest,
					async: false,
					success: function(data) {
						/*
							#CONTENT字段保存为json字符串
							{
							  disabled: {boolean} 	# 是否不显示监控
							  scrollTask: {integer}	# 多个队列时的滚屏间隔，单位为毫秒
							  waitAlert: {integer}	# 等待数阈值，超过该阀值将会改变颜色提示
							  alertColor: {string}	# 告警颜色，与waitAlert配合
							  color: ${string}	# 队列信息的正常颜色
							  queues : {
								'5000': ['agent', 'busy'],	# 五个可用字段分别为：agent, ready, wait, busy, lwt
								'6000': ['busy', 'lwt']		# 系统将按照配置的顺序进行展示
							  },
							  // total_agent 总坐席数， online_agent 在线坐席数， active_session 活动会话数， waiting_request 等待请求数， longest_waiting 最长等待时长， average_chating 平均聊天时长，longest_chating 最长聊天时长
							  "chatQueues": {
								98: ["total_agent", "online_agent", "active_session", "waiting_request", "longest_waiting", "average_chating", "longest_chating"], // 对应到chat_queue_monitor中的字段，最多可以这7个
								99: ["online_agent", "active_session", "waiting_request"]
							  }
							}
             			*/
						if (data.code > 0) {
							if (data.value[0].count > 0) {
								$E.wlCfg = JSON.parse(data.value[0].fields[0][0] || '{}');
							} else if (data.value[1].count > 0) {
								$E.wlCfg = JSON.parse(data.value[1].fields[0][0] || '{}');
							} else if (data.value[2].count > 0) {
								$E.wlCfg = JSON.parse(data.value[2].fields[0][0] || '{}');
							}
							if (data.value[3].count > 0) {
								$.each(data.value[3].fields, function(i, v) {
									dnlist[v[0].trim()] = v[1].trim();
								})
							}
							if (data.value[4].count > 0) {
								$.each(data.value[4].fields, function(i, v) {
									chatQueues[v[0]] = v[1].trim();
								})
							}
							if ((isCTIMode() && $E.wlCfg.queues) || ($E.agentMonitor.chat && $E.wlCfg.chatQueues)) {
								var ul = $('ul#agentMonitor').empty(), liStr, li;
								// 初始化电话队列
								if (isCTIMode() && $E.wlCfg.queues) {
									for (var queue in $E.wlCfg.queues) {
										liStr = '<li><span class="more b">(' + (dnlist[queue] || queue) + ')</span>';
										$.each($E.wlCfg.queues[queue], function(i, v) {
											if (v === 'agent')
												liStr += '<span>登录：</span><span class="js_am_agent more">0</span>';
											else if (v === 'ready')
												liStr += '<span>就绪：</span><span class="js_am_ready more">0</span>';
											else if (v === 'wait')
												liStr += '<span class="waitdom">等待：</span><span class="waitdom js_am_wait more">0</span>';
											else if (v === 'busy')
												liStr += '<span>忙碌：</span><span class="js_am_busy more">0</span>';
											else if (v === 'lwt')
												liStr += '<span>最长等待：</span><span class="js_am_lwt">0</span></li>';
										});
										li = $(liStr).appendTo(ul);
										$E.staff.queues[queue] = {
											dom: li,
											entity: {}
										}
									}
									$F.log('Elite', 'DNLIST information', dnlist);
									$F.log('Elite', 'Queues for staff', $E.staff.queues);
								}
								// 初始化聊天队列
								if ($E.agentMonitor.chat && $E.wlCfg.chatQueues) {
									Object.keys($E.wlCfg.chatQueues).forEach(queue => {
										liStr = '<li><span class="more b">(' + (chatQueues[queue] || queue) + ')</span>';
										$E.wlCfg.chatQueues[queue] && $E.wlCfg.chatQueues[queue].forEach(t => {
											switch (t) {
												case "total_agent":
													liStr += '<span>总坐席：</span><span class="js_chat_total_agent more">0</span>';
													break;
												case "online_agent":
													liStr += '<span>在线：</span><span class="js_chat_online_agent more">0</span>';
													break;
												case "active_session":
													liStr += '<span>会话：</span><span class="js_chat_active_session more">0</span>';
													break;
												case "waiting_request":
													liStr += '<span>排队：</span><span class="js_chat_waiting_request more">0</span>';
													break;
												case "longest_waiting":
													liStr += '<span>最长等待：</span><span class="js_chat_longest_waiting more">0</span>';
													break;
												case "average_chating":
													liStr += '<span>平均聊天：</span><span class="js_chat_average_chating more">0</span>';
													break;
												case "longest_chating":
													liStr += '<span>最长聊天：</span><span class="js_chat_longest_chating more">0</span>';
													break;
												default:
													break;
											}
										});
										li = $(liStr).appendTo(ul);
										$E.staff.chatQueues[queue] = {
											dom: li,
											entity: {}
										}
									});

									$E.wlCfg.chatWorkloadTask && clearTimeout($E.wlCfg.chatWorkloadTask);
									const doChatWorkloadTask = function() {
										$E.wlCfg.chatWorkloadTask = setTimeout(() => {
											$F.dataService('SystemDo2', {
												silent: true,
												data: {
													token: project.token,
													dbPool: '',
													sqls: [{
														key: 'wl.chat.queue.monitor'
													}]
												},
												digest: project.digest,
												async: true,
												success: function (data) {
													if (data.value[0].count > 0) {
														$('#agentMonitor').show();
														data.value[0].fields.forEach((f) => {
															if ($E.staff.chatQueues[f[0]]) {
																$E.staff.chatQueues[f[0]].entity = f;
																var li = $E.staff.chatQueues[f[0]].dom;
																$('.js_chat_total_agent', li).text(f[1]);
																$('.js_chat_online_agent', li).text(f[2]);
																$('.js_chat_active_session', li).text(f[3]);
																$('.js_chat_waiting_request', li).text(f[4]);
																$('.js_chat_longest_waiting', li).text(f[5]);
																$('.js_chat_average_chating', li).text(f[6]);
																$('.js_chat_longest_chating', li).text(f[7]);
															}
														});
													}
												}
											});
											doChatWorkloadTask();
										}, 10000);
									}
									doChatWorkloadTask();
									$F.log('Elite', 'ChatQueues information', chatQueues);
									$F.log('Elite', 'ChatQueues for staff', $E.staff.chatQueues);
								}

								//右下角跑马灯
								$E.wlCfg.task && clearTimeout($E.wlCfg.task);
								const doAgentMonitorTask = function() {
									$E.wlCfg.task = setTimeout(function() {
										ul.animate({
											top: '-3em'
										}, 500, 'linear', function() {
											ul.css('top', 0);
											$('>li:eq(0)', ul).remove().appendTo(ul);
											doAgentMonitorTask();
										})
									}, $E.wlCfg.scrollTask || 5000);
								}
								doAgentMonitorTask();
							}
							if (!$E.wlCfg.disabled) {
								$('#agentMonitor').show();
							} else {
								$('#agentMonitor').hide();
							}
						} else {
							$F.err(data.message);
						}
					}
				});
				$F.log('Elite', 'WSCTIConfig config', $E.wlCfg);

				if ($E.wlCfg.color) {
					$('ul#agentMonitor').css('color', $E.wlCfg.color);
				}
			}
		},

		processWorkload = function(e) {
			if (! $E.wlCfg) {
				return;
			}

			if ($E.wlCfg.disabled) {
				// 自定义配置不显示队列信息
				$E.ws.workload.proxy.close();
				return;
			}

			let info = {}, cs = {}, queueInfo;
			if ($E.agentMonitor.source === 'queueInfo') {
				if (! e.queueinfo)
					return;

				queueInfo = e.queueinfo.split('|');
				$.each(queueInfo, function(i, v) {
					var q = v.split('=');
					cs[q[0]] = q[1];
				});
				info.queue = cs.queue;
				info.agent = cs[$E.agentMonitor.agentField || 'login'];
				info.ready = cs[$E.agentMonitor.readyField || 'ready'];
				info.wait = cs[$E.agentMonitor.waitField || 'wait'];
				info.busy = cs[$E.agentMonitor.busyField || 'busy'];
				info.lwt = cs[$E.agentMonitor.lwtField || 'longestwaittime'];
			} else if ($E.agentMonitor.source === 'HuaweiMCP') {
				if (! e.queueinfo)
					return;
				queueInfo = e.queueinfo.split('|');
				let q;
				$.each(queueInfo, function(i, v) {
					q = v.split('=');
					cs[q[0]] = q[1];
				});
				info.queue = e.queue;
				info.agent = cs['logonagents'];
				info.ready = cs['availagents'];
				info.wait = cs['queuesize'];
				//info.busy = cs[$E.agentMonitor.busyField || 'busy'];
				//info.lwt = cs[$E.agentMonitor.lwtField || 'longestwaittime'];
			} else {
				if (e.queueinfo)
					return;

				info.queue = e.queue;
				info.agent = e.totalagent;
				info.ready = e.totalready;
				info.wait = e.totalwait;
				info.busy = e.totalbusy;
				info.lwt = e.longestwaittime;
			}
			info.date = $F.parseDate(e.msgtime);
			// console.log(info);

			if (! $E.staff.queues[info.queue]) {
				return;
			}
			$E.staff.queues[info.queue].entity = info;

			$('#agentMonitor').show();
			let li = $E.staff.queues[info.queue].dom;
			$('.js_am_agent', li).text(info.agent);
			$('.js_am_ready', li).text(info.ready);
			$('.js_am_wait', li).text(info.wait);
			$('.js_am_busy', li).text(info.busy);
			$('.js_am_lwt', li).text(info.lwt);

			//console.error(info.wait + ' vs ' + parseInt($E.agentMonitor.waitAlert||5));
			if (info.wait >= parseInt($E.wlCfg.waitAlert || $E.agentMonitor.waitAlert)) {
				if ($E.wlCfg.alertColor)
					$('.waitdom', li).css('color', $E.wlCfg.alertColor)
				else
					$('.waitdom', li).css('color', 'red')
			} else {
				$('.waitdom', li).css('color', '');
			}
		};

	$E.init = function() {
		setTimeout(function() {
			require.config({
				urlArgs : 'v=' + $E.ver,
				waitSeconds : 0,
				baseUrl: $E.url || '/'
			});
			require(['js/lib/dayjs.min'], function(dayjs) {
				window.dayjs = dayjs;
				init();
			})
		}, 10)
	};

	$(function() {
		if (!$E.debug) {
			document.oncontextmenu = function () {
				return $E.staff.consolable;
			}
			document.oncopy = function () {
				return $E.staff.consolable;
			}
			document.onkeydown = function (event) {
				if (event.ctrlKey || event.metaKey || event.key === 'F12') {
					return $E.staff.consolable;
				}
			}
		}
		if ($E.query !== 'mf') {
			$E.init();
		}
	});

})(jQuery);
